home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / CW GUSI 1.6.4 / src / GUSIBuffer.cp < prev    next >
Text File  |  1995-04-02  |  5KB  |  307 lines

  1. /*********************************************************************
  2. Project    :    GUSI                -    Grand Unified Socket Interface
  3. File        :    GUSIBuffer.cp    -    Circular buffers and Scatter/Gather
  4. Author    :    Matthias Neeracher
  5. Language    :    MPW C/C++
  6.  
  7. $Log: GUSIBuffer.cp,v $
  8. Revision 1.2  1994/12/30  19:40:32  neeri
  9. fix a bug which was sabotaging all vectored routines.
  10.  
  11. Revision 1.1  1994/02/25  02:28:25  neeri
  12. Initial revision
  13.  
  14. Revision 0.4  1993/07/17  00:00:00  neeri
  15. proc -> defproc
  16.  
  17. Revision 0.3  1993/02/10  00:00:00  neeri
  18. The above was incorrect, next attempt
  19.  
  20. Revision 0.2  1992/08/23  00:00:00  neeri
  21. Optimize buffer size for empty buffers
  22.  
  23. Revision 0.1  1992/08/02  00:00:00  neeri
  24. Deferred procedures
  25.  
  26. *********************************************************************/
  27.  
  28. #ifndef GUSI_BUFFER_DEBUG
  29. #define NDEBUG
  30. #endif
  31.  
  32. #include <assert.h>
  33.  
  34. #include "GUSI_P.h"
  35.  
  36. #pragma segment GUSI
  37.  
  38. /**************************** RingBuffer ****************************/
  39.  
  40. int RingDist(Ptr start, Ptr end, Ptr from, Ptr to)
  41. {
  42.     if (from > to)
  43.         return RingDist(start, end, from, end)+RingDist(start, end, start, to);
  44.     else
  45.         return to-from;
  46. }
  47.  
  48. #define RINGEQ(from, to, val)    \
  49.     (RingDist(buffer, endbuf, (from), (to)) == ((val)%(endbuf-buffer)))
  50. #define INVAR                                    \
  51.     (    (free >= 0)                             \
  52.     && (valid >= 0)                             \
  53.     &&    RINGEQ(consume, produce, valid+spare) \
  54.     &&    RINGEQ(produce, consume, free))
  55.  
  56. RingBuffer::RingBuffer(u_short bufsiz)
  57. {
  58.     buffer    =    NewPtr(bufsiz);
  59.     endbuf    =    buffer+bufsiz;
  60.     consume    =    buffer;
  61.     produce    =    buffer;
  62.     free        =    bufsiz;
  63.     valid        =    0;
  64.     spare        =    0;
  65.     lock        =    false;
  66.     defproc    =    nil;
  67.     
  68.     assert(INVAR);
  69.     assert(endbuf - buffer == bufsiz);
  70. }
  71.  
  72. RingBuffer::~RingBuffer()
  73. {
  74.     Defer();
  75.     if (buffer)
  76.         DisposPtr(buffer);
  77. }
  78.  
  79. Ptr RingBuffer::Producer(long & len)
  80. {
  81.     Defer();
  82.     
  83. #ifndef NDEBUG
  84.     long    oldlen    =    len;
  85. #endif
  86.  
  87.     if (!valid) {
  88.         produce = buffer;
  89.         consume = buffer;
  90.         spare   = 0;
  91.     }
  92.     
  93.     u_short    streak    =    endbuf - produce;
  94.     Ptr        res        =    produce;
  95.     
  96.     if (streak >= free)
  97.         streak = free;
  98.     else if (streak < (free >> 1) && streak < len) {
  99.         spare     =  streak;
  100.         produce    =    buffer;
  101.         free        -=    spare;
  102.         streak    =    free;
  103.         res         =    produce;
  104.     }
  105.     
  106.     if (len > streak)
  107.         len    =    streak;
  108.     
  109.     assert(INVAR);
  110.     assert(len <= oldlen);
  111.     
  112.     Undefer();
  113.     
  114.     return res;
  115. }
  116.  
  117. Ptr RingBuffer::Consumer(long & len)
  118. {
  119.     Defer();
  120.     
  121. #ifndef NDEBUG
  122.     long    oldlen    =    len;
  123. #endif
  124.  
  125.     u_short    streak    =    endbuf - consume - spare;
  126.     Ptr        res        =    consume;
  127.     
  128.     if (streak > valid)
  129.         streak = valid;
  130.     if (len > streak)
  131.         len    =    streak;
  132.     
  133.     assert(INVAR);
  134.     assert(len <= oldlen);
  135.     
  136.     Undefer();
  137.     
  138.     return res;
  139. }
  140.  
  141. void RingBuffer::Validate(long len)
  142. {
  143.     Defer();
  144.     
  145.     valid     += (unsigned short) len;
  146.     free        -=    (unsigned short) len;
  147.     produce    +=    len;
  148.     
  149.     if (produce == endbuf)
  150.         produce    =    buffer;
  151.     
  152.     assert(INVAR);
  153.     
  154.     Undefer();
  155. }
  156.  
  157. void RingBuffer::Invalidate(long len)
  158. {
  159.     Defer();
  160.     
  161.     free         += (unsigned short) len;
  162.     valid        -=    (unsigned short) len;
  163.     consume    +=    len;
  164.     
  165.     if (consume == endbuf-spare) {
  166.         consume    =    buffer;
  167.         spare        =    0;
  168.     } else if (!valid && free == len)    {        // Maximize streak for empty buffer
  169.         consume    =    buffer;
  170.         produce    =    buffer;
  171.     }
  172.     
  173.     assert(INVAR);
  174.     
  175.     Undefer();
  176. }
  177.  
  178. void RingBuffer::Consume(Ptr to, long & len)
  179. {
  180. #ifndef NDEBUG
  181.     Ptr    oldto        =    to;
  182.     long    oldlen    =    len;
  183. #endif
  184.  
  185.     long    part;
  186.     long    rest;
  187.     Ptr    buf;
  188.     
  189.     for (rest = len; (part = rest) && valid; rest -= part)    {
  190.         buf    =    Consumer(part);
  191.         BlockMove(buf, to, part);
  192.         Invalidate(part);
  193.         to        += part;
  194.     }
  195.     
  196.     len    -=    rest;
  197.     
  198.     assert(INVAR);
  199.     assert(len <= oldlen);
  200.     assert(to-oldto == len);
  201. }
  202.  
  203. void RingBuffer::Produce(Ptr from, long & len)
  204. {
  205. #ifndef NDEBUG
  206.     Ptr    oldfrom    =    from;
  207.     long    oldlen    =    len;
  208. #endif
  209.  
  210.     long    part;
  211.     long    rest;
  212.     Ptr    buf;
  213.     
  214.     for (rest = len; (part = rest) && free; rest -= part)    {
  215.         buf    =    Producer(part);
  216.         BlockMove(from, buf, part);
  217.         Validate(part);
  218.         
  219.         from    += part;
  220.     }
  221.     
  222.     len    -=    rest;
  223.     
  224.     assert(INVAR);
  225.     assert(len <= oldlen);
  226.     assert(from-oldfrom == len);
  227. }
  228.  
  229. /************************** Scatter/Gather **************************/
  230.  
  231. ScattGath::ScattGath(const struct iovec *iov, int cnt)    {
  232.     io        =    iov;
  233.     count    =    cnt;
  234.  
  235.     if (count < 1)    {
  236.         buf        =    nil;
  237.         len        =    0;
  238.         scratch    =    nil;
  239.     } else if (count == 1)    {    
  240.         buf        =    (void *) iov->iov_base;
  241.         len        =    (int)    iov->iov_len;
  242.         scratch    =    nil;
  243.     } else {
  244.         for (len = 0; cnt--; ++iov)
  245.             len += (int) iov->iov_len;
  246.         
  247.         scratch = NewHandle(len);
  248.         
  249.         if (scratch)    {
  250.             HLock(scratch);
  251.             buf    =    (void *) *scratch;
  252.         } else
  253.             buf     =    nil;
  254.     }
  255. }
  256.  
  257. ScattGath::~ScattGath()
  258. {
  259.     if (scratch)
  260.         DisposHandle(scratch);
  261. }
  262.  
  263. Scatterer::Scatterer(const struct iovec *iov, int count) 
  264.     : ScattGath(iov, count)
  265. {
  266. }
  267.  
  268. Scatterer::~Scatterer()
  269. {
  270.     int    sect;
  271.     
  272.     if (count > 1 && buf)
  273.         for (char * bptr = (char *) buf; count-- && len; ++io)    {
  274.             sect    =    min(len, io->iov_len);
  275.             
  276.             memcpy(io->iov_base, bptr, sect);
  277.             
  278.             bptr    +=    sect;
  279.             len     -=    sect;
  280.         }
  281. }
  282.  
  283. Gatherer::Gatherer(const struct iovec *iov, int count) 
  284.     : ScattGath(iov, count)
  285. {
  286.     if (count > 1 && buf)
  287.         for (char * bptr = (char *) buf; count--; ++iov)    {
  288.             memcpy(bptr, iov->iov_base, iov->iov_len);
  289.             
  290.             bptr    +=    iov->iov_len;
  291.         }
  292. }
  293.  
  294. Gatherer::~Gatherer()
  295. {
  296. }
  297.  
  298. void CopyC2PStr(const char * cstr, StringPtr pstr)
  299. {
  300.     int    len;
  301.     
  302.     for (len = 0; *cstr && len<255; pstr[++len] = *cstr++)
  303.         ;
  304.     
  305.     pstr[0] = len;
  306. }
  307.